/*
 * @Author: lei
 * @Description: 常见运算符重载
 * @FilePath: /code/overload/operator_overload.cc
 */
#include <iomanip>
#include <iostream>
using namespace std;
// g++ -o operator_overload operator_overload.cc -std=c++11

// 重载>>和<<号
class complex {
 public:
  complex(double real = 0.0, double imag = 0.0) : m_real(real), m_imag(imag){};

 public:
  friend complex operator+(const complex &A, const complex &B);
  friend complex operator-(const complex &A, const complex &B);
  friend complex operator*(const complex &A, const complex &B);
  friend complex operator/(const complex &A, const complex &B);
  friend istream &operator>>(istream &in, complex &A);
  friend ostream &operator<<(ostream &out, complex &A);

 private:
  double m_real;  //实部
  double m_imag;  //虚部
};

//重载加法运算符
complex operator+(const complex &A, const complex &B) {
  complex C;
  C.m_real = A.m_real + B.m_real;
  C.m_imag = A.m_imag + B.m_imag;
  return C;
}

//重载减法运算符
complex operator-(const complex &A, const complex &B) {
  complex C;
  C.m_real = A.m_real - B.m_real;
  C.m_imag = A.m_imag - B.m_imag;
  return C;
}

//重载乘法运算符
complex operator*(const complex &A, const complex &B) {
  complex C;
  C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
  C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
  return C;
}

//重载除法运算符
complex operator/(const complex &A, const complex &B) {
  complex C;
  double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
  C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag) / square;
  C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag) / square;
  return C;
}

//重载输入运算符
istream &operator>>(istream &in, complex &A) {
  in >> A.m_real >> A.m_imag;
  return in;
}

//重载输出运算符
ostream &operator<<(ostream &out, complex &A) {
  out << A.m_real << " + " << A.m_imag << " i ";
  return out;
}
void test1() {
  complex c1, c2, c3;
  cin >> c1 >> c2;

  c3 = c1 + c2;
  cout << "c1 + c2 = " << c3 << endl;

  c3 = c1 - c2;
  cout << "c1 - c2 = " << c3 << endl;

  c3 = c1 * c2;
  cout << "c1 * c2 = " << c3 << endl;

  c3 = c1 / c2;
  cout << "c1 / c2 = " << c3 << endl;
}

// 测试[]
class Array {
 public:
  Array(int length = 0);
  ~Array();

 public:
  int &operator[](int i);
  const int &operator[](int i) const;  // 防止常对象调用[]出错

 public:
  int length() const { return m_length; }
  void display() const;

 private:
  int m_length;  //数组长度
  int *m_p;      //指向数组内存的指针
};

Array::Array(int length) : m_length(length) {
  if (length == 0) {
    m_p = NULL;
  } else {
    m_p = new int[length];
  }
}

Array::~Array() { delete[] m_p; }

int &Array::operator[](int i) { return m_p[i]; }

const int &Array::operator[](int i) const { return m_p[i]; }

void Array::display() const {
  for (int i = 0; i < m_length; i++) {
    if (i == m_length - 1) {
      cout << m_p[i] << endl;
    } else {
      cout << m_p[i] << ", ";
    }
  }
}
void test2() {
  int n;
  cin >> n;

  Array A(n);
  for (int i = 0, len = A.length(); i < len; i++) {
    A[i] = i * 5;
  }
  A.display();

  const Array B(n);
  cout << B[n - 1] << endl;  //访问最后一个元素
}

// 重载++和--
//秒表类
class stopwatch {
 public:
  stopwatch() : m_min(0), m_sec(0) {}

 public:
  void setzero() {
    m_min = 0;
    m_sec = 0;
  }
  stopwatch run();            // 运行
  stopwatch operator++();     // ++i，前置形式,编译器规定
  stopwatch operator++(int);  // i++，后置形式,编译器规定
  friend ostream &operator<<(ostream &, const stopwatch &);

 private:
  int m_min;  //分钟
  int m_sec;  //秒钟
};

stopwatch stopwatch::run() {
  ++m_sec;
  if (m_sec == 60) {
    m_min++;
    m_sec = 0;
  }
  return *this;
}

// 前置++
stopwatch stopwatch::operator++() { return run(); }

// 后置++
stopwatch stopwatch::operator++(
    int n) {  // 在这个函数中参数n是没有任何意义的，它的存在只是为了区分是前置形式还是后置形式。

  stopwatch s = *this;
  run();
  return s;
}

ostream &operator<<(ostream &out, const stopwatch &s) {
  out << setfill('0') << setw(2) << s.m_min << ":" << setw(2) << s.m_sec;
  return out;
}

void test3() {
  stopwatch s1, s2;

  s1 = s2++;
  cout << "s1: " << s1 << endl;
  cout << "s2: " << s2 << endl;
  s1.setzero();
  s2.setzero();

  s1 = ++s2;
  cout << "s1: " << s1 << endl;
  cout << "s2: " << s2 << endl;
}

// 类型强制转换运算符重载
class Complex {
  double real, imag;

 public:
  Complex(double r = 0, double i = 0) : real(r), imag(i){};
  operator double() { return real; }  //重载强制类型转换运算符 double
};
void test4() {
  Complex c(1.2, 3.4);
  cout << (double)c << endl;  //输出 1.2 ,(double)c等价于c.operator double()。
  double n = 2 + c;           //等价于 double n = 2 + c. operator double()
  cout << n;                  //输出 3.2
}
int main() {
  //   test1();
  //   test2();
  //   test3();
  test4();
  return 0;
}